There are two types of files in MS-DOS systems:
The following are the commands and statements most frequently used with program files. The GW-BASIC User's Reference contains more information on each of them.
SAVE filename[,a][,p]
Writes to diskette the program currently residing in memory.
LOAD filename[,r]
Loads the program from a diskette into memory. LOAD deletes the current contents of memory and closes all files before loading the program.
RUN filename[,r]
Loads the program from a diskette into memory and runs it immediately. RUN deletes the current contents of memory and closes all files before loading the program.
MERGE filename
Loads the program from a diskette into memory, but does not delete the current program already in memory.
KILL filename
Deletes the file from a diskette. This command can also be used with data files.
NAME old filename AS new filename
Changes the name of a diskette file. Only the name of the file is changed. The file is not modified, and it remains in the same space and position on the disk. This command can also be used with data files.
GW-BASIC programs can work with two types of data files:
Sequential files are easier to create than random access files, but are limited in flexibility and speed when accessing data. Data written to a sequential file is a series of ASCII characters. Data is stored, one item after another (sequentially), in the order sent. Data is read back in the same way.
Creating and accessing random access files requires more program steps than sequential files, but random files require less room on the disk, because GW-BASIC stores them in a compressed format in the form of a string.
The following sections discuss how to create and use these two types of data files.
The following statements and functions are used with sequential files:
CLOSE | LOF |
EOF | OPEN |
INPUT# | PRINT# |
LINE INPUT# | PRINT# USING |
LOC | UNLOCK |
LOCK | WRITE# |
The following program steps are required to create a sequential file and access the data in the file:
Open the file in output (O) mode. The current program will use this file first for output:
OPEN "O",#1,"filename"
Write data to the file using the PRINT# or WRITE# statement:
PRINT#1,A$ PRINT#1,B$ PRINT#1,C$
To access the data in the file, you must close the file and reopen it in input (I) mode:
CLOSE #1 OPEN "I",#1,"filename
Use the INPUT# or LINE INPUT# statement to read data from the sequential file into the program:
INPUT#1,X$,Y$,Z$
Example 1 is a short program that creates a sequential file, data, from information input at the terminal.
10 OPEN "O",#1,"DATA" 20 INPUT "NAME";N$ 30 IF N$="DONE" THEN END 40 INPUT "DEPARTMENT";D$ 50 INPUT "DATE HIRED";H$ 60 PRINT#1,N$;","D$",";H$ 70 PRINT:GOTO 20 RUN NAME? MICKEY MOUSE DEPARTMENT? AUDIO/VISUAL AIDS DATE HIRED? 01/12/72 NAME? SHERLOCK HOLMES DEPARTMENT? RESEARCH DATE HIRED? 12/03/65 NAME? EBENEEZER SCROOGE DEPARTMENT? ACCOUNTING DATE HIRED? 04/27/78 NAME? SUPER MANN DEPARTMENT? MAINTENANCE DATE HIRED? 08/16/78 NAME? DONE OK
The program in Example 2 accesses the file data, created in the program in Example 1, and displays the name of everyone hired in 1978.
10 OPEN "I",#1,"DATA" 20 INPUT#1,N$,D$,H$ 30 IF RIGHT$(H$,2)="78" THEN PRINT N$ 40 GOTO 20 50 CLOSE #1 RUN EBENEEZER SCROOGE SUPER MANN Input past end in 20 Ok
The program in Example 2 reads, sequentially, every item in the file. When all the data has been read, line 20 causes an "Input past end" error. To avoid this error, insert line 15, which uses the EOF function to test for end of file:
15 IF EOF(1) THEN END
and change line 40 to GOTO 15.
A program that creates a sequential file can also write formatted data to the diskette with the PRINT# USING statement. For example, the following statement could be used to write numeric data to diskette without explicit delimiters:
PRINT#1, USING"####.##,"; A, B, C, D
The comma at the end of the format string serves to separate the items in the disk file.
The LOC function, when used with a sequential file, returns the number of 128-byte records that have been written to or read from the file since it was opened.
When a sequential file is opened in O mode, the current contents are destroyed. To add data to an existing file without destroying its contents, open the file in append (A) mode.
The program in Example 3 can be used to create, or to add onto a file called names. This program illustrates the use of LINE INPUT. LINE INPUT will read in characters until it sees a carriage return indicator, or until it has read 255 characters. It does not stop at quotation marks or commas.
10 ON ERROR GOTO 2000 20 OPEN "A", #1, "NAMES" 110 REM ADD NEW ENTRIES TO FILE 120 INPUT "NAME"; N$ 130 IF N$="" THEN 200 `CARRIAGE RETURN EXITS INPUT LOOP 140 LINE INPUT "ADDRESS? "; A$ 150 LINE INPUT "BIRTHDAY? "; B$ 160 PRINT#1, N$ 170 PRINT#1, A$ 180 PRINT#1, B$ 190 PRINT: GOTO 120 200 CLOSE #1 2000 ON ERROR GOTO 0
In lines 10 and 2000 the ON ERROR GOTO statement is being used. This statement enables error trapping and specifies the first line (2000) of the error handling subroutine. Line 10 enables the error handling routine. Line 2000 disables the error handling routine and is the point where GW-BASIC branches to print the error messages.
Information in random access files is stored and accessed in distinct, numbered units called records. Since the information is called by number, the data can be called from any disk location; the program needn't read the entire disk, as when seeking sequential files, to locate data. GW-BASIC supports large random files. The maximum logical record number is 232 -1.
The following statements and functions are used with random files:
CLOSE | FIELD | MKI$ |
CVD | LOC | MKS$ |
CVI | LOCK | OPEN |
CVS | LOF | PUT |
EOF | LSET/RSET | UNLOCK |
ET | MKD$ |
The following program steps are required to create a random data file:
Open the file for random access (R) mode. The following example specifies a record length of 32 bytes. If the record length is omitted, the default is 128 bytes.
OPEN "R", #1, "filename", 32
Use the FIELD statement to allocate space in the random buffer for the variables that will be written to the random file:
FIELD#1, 20 AS N$, 4 AS A$, 8 AS P$
In this example, the first 20 positions (bytes) in the random file buffer are allocated to the string variable N$. The next 4 positions are allocated to A$; the next 8 to P$.
Use LSET or RSET to move the data into the random buffer fields in left- or right-justified format (L=left SET;R=right SET). Numeric values must be made into strings when placed in the buffer. MKI$ converts an integer value into a string; MKS$ converts a single-precision value, and MKD$ converts a double-precision value.
LSET N$=X$ LSET A$=MKS$(AMT) LSET P$=TEL$
Write the data from the buffer to the diskette using the PUT statement:
PUT #1, CODE%
The program in Example 4 takes information keyed as input at the terminal and writes it to a random access data file. Each time the PUT statement is executed, a record is written to the file. In the example, the 2-digit CODE% input in line 30 becomes the record number.
Note
Do not use a fielded string variable in an INPUT or LET statement. This causes the pointer for that variable to point into string space instead of the random file buffer.
10 OPEN "R", #1, "INFOFILE", 32 20 FIELD#1, 20 AS N$, 4 AS A$, 8 AS P$ 30 INPUT "2-DIGIT CODE"; CODE% 40 INPUT "NAME"; X$ 50 INPUT "AMOUNT"; AMT 60 INPUT "PHONE"; TEL$: PRINT 70 LSET N$=X$ 80 LSET A$=MKS$(AMT) 90 LSET P$=TEL$ 100 PUT #1, CODE% 110 GOTO 30
The following program steps are required to access a random file:
Open the file in R mode:
OPEN "R", #1, "filename", 32
Use the FIELD statement to allocate space in the random buffer for the variables that will be read from the file:
FIELD, #1, 20 AS N$, 4 AS A$, 8 AS P$
In this example, the first 20 positions (bytes) in the random file buffer are allocated to the string variable N$. The next 4 positions are allocated to A$; the next 8 to P$.
Note
In a program that performs both INPUT and OUTPUT on the same random file, you can often use just one OPEN statement and one FIELD statement.
Use the GET statement to move the desired record into the random buffer.
GET #1, CODE%
The data in the buffer can now be accessed by the program.
Convert numeric values back to numbers using the convert functions: CVI for integers, CVS for single-precision values, and CVD for double-precision values.
PRINT N$ PRINT CVS(A$) . . .
The program in Example 5 accesses the random file, infofile, that was created in Example 4. By inputting the 3-digit code, the information associated with that code is read from the file and displayed.
10 OPEN "R",#1,"INFOFILE",32 20 FIELD #1, 20 AS N$, 4 AS A$, 8 AS P$ 30 INPUT "2-DIGIT CODE";CODE% 40 GET #1, CODE% 50 PRINT N$ 60 PRINT USING "$$###.##";CVS(A$) 70 PRINT P$:PRINT 80 GOTO 30
With random files, the LOC function returns the current record number. The current record number is the last record number used in a GET or PUT statement. For example, the following line ends program execution if the current record number in file#1 is higher than 99:
IF LOC(1)>99 THEN END
Example 6 is an inventory program that illustrates random file access. In this program, the record number is used as the part number, and it is assumed that the inventory will contain no more than 100 different part numbers.
Lines 900-960 initialize the data file by writing CHR$(255) as the first character of each record. This is used later (line 270 and line 500) to determine whether an entry already exists for that part number.
Lines 130-220 display the different inventory functions that the program performs. When you type in the desired function number, line 230 branches to the appropriate subroutine.
120 OPEN"R",#1,"INVEN.DAT",39 125 FIELD#1,1 AS F$,30 AS D$, 2 AS Q$,2 AS R$,4 AS P$ 130 PRINT:PRINT "FUNCTIONS:":PRINT 135 PRINT 1,"INITIALIZE FILE" 140 PRINT 2,"CREATE A NEW ENTRY" 150 PRINT 3,"DISPLAY INVENTORY FOR ONE PART" 160 PRINT 4,"ADD TO STOCK" 170 PRINT 5,"SUBTRACT FROM STOCK" 180 PRINT 6,"DISPLAY ALL ITEMS BELOW REORDER LEVEL" 220 PRINT:PRINT:INPUT"FUNCTION";FUNCTION 225 IF (FUNCTION<1)OR(FUNCTION>6) THEN PRINT "BAD FUNCTION NUMBER":GOTO 130 230 ON FUNCTION GOSUB 900,250,390,480,560,680 240 GOTO 220 250 REM BUILD NEW ENTRY 260 GOSUB 840 270 IF ASC(F$) < > 255 THEN INPUT"OVERWRITE";A$: IF A$ < > "Y" THEN RETURN 280 LSET F$=CHR$(0) 290 INPUT "DESCRIPTION";DESC$ 300 LSET D$=DESC$ 310 INPUT "QUANTITY IN STOCK";Q% 320 LSET Q$=MKI$(Q%) 330 INPUT "REORDER LEVEL";R% 340 LSET R$=MKI$(R%) 350 INPUT "UNIT PRICE";P 360 LSET P$=MKS$(P) 370 PUT#1,PART% 380 RETURN 390 REM DISPLAY ENTRY 400 GOSUB 840 410 IF ASC(F$)=255 THEN PRINT "NULL ENTRY":RETURN 420 PRINT USING "PART NUMBER ###";PART% 430 PRINT D$ 440 PRINT USING "QUANTITY ON HAND #####";CVI(Q$) 450 PRINT USING "REORDER LEVEL #####";CVI(R$) 460 PRINT USING "UNIT PRICE $$##.##";CVS(P$) 470 RETURN 480 REM ADD TO STOCK 490 GOSUB 840 500 IF ASC(F$)=255 THEN PRINT "NULL ENTRY":RETURN 510 PRINT D$:INPUT "QUANTITY TO ADD";A% 520 Q%=CVI(Q$)+A% 530 LSET Q$=MKI$(Q%) 540 PUT#1,PART% 550 RETURN 560 REM REMOVE FROM STOCK 570 GOSUB 840 580 IF ASC(F$)=255 THEN PRINT "NULL ENTRY":RETURN 590 PRINT D$ 600 INPUT "QUANTITY TO SUBTRACT";S% 610 Q%=CVI(Q$) 620 IF (Q%-S%)<0 THEN PRINT "ONLY";Q%;"IN STOCK" :GOTO 600 630 Q%=Q%-S% 640 IF Q%= < CVI(R$) THEN PRINT "QUANTITY NOW";Q%;"REORDER LEVEL";CVI(R$) 650 LSET Q$=MKI$(Q%) 660 PUT#1,PART% 670 RETURN 680 REM DISPLAY ITEMS BELOW REORDER LEVEL4 690 FOR I=1 TO 100 710 GET#1,I 720 IF CVI(Q$)<CVI(R$) THEN PRINT D$;"QUANTITY";CVI(Q$) TAB(50) "REORDER LEVEL";CVI(R$) 730 NEXT I 740 RETURN 840 INPUT "PART NUMBER";PART% 850 IF(PART% < 1)OR(PART% > 100) THEN PRINT "BAD PART NUMBER":GOTO 840 ELSE GET#1,PART%:RETURN 890 END 900 REM INITIALIZE FILE 910 INPUT "ARE YOU SURE";B$:IF B$ < > "Y" THEN RETURN 920 LSET F$=CHR$(255) 930 FOR I=1 TO 100 940 PUT#1,I 950 NEXT I 960 RETURN